// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @type {{
 *  contentModel: !Object.<string, !ContentModel>,
 *  define: function(string, !Object),
 *  defineCommand: function(string, !function()),
 *  isContentEditable: function(!Node) : boolean,
 *  lookupCommand: function(string) : ?CommandFunction,
 *  newSet: function(!Array) : !Set,
 *  nodes: {
 *    computeEffectiveNodes: function(!editing.ReadOnlySelection) : !Array.<!Node>,
 *    computeSelectedNodes: function(!editing.ReadOnlySelection) : !Array.<!Node>,
 *    isDescendantOf: function(!Node, !Node) : boolean,
 *    isEditable: function(!Node) : boolean,
 *    isElement: function(!Node) : boolean,
 *    isInteractive: function(!Node) : boolean,
 *    isPhrasing: function(!Node) : boolean,
 *    isText: function(!Node) : boolean,
 *    isVisibleNode: function(!Node) : boolean,
 *    isWhitespaceNode: function(!Node) : boolean,
 *    maxOffset: function(!Node) : number,
 *    nextNodeSkippingChildren: function(?Node) : ?Node,
 *    nodeIndex: function(!Node): number,
 *    normalizeSelection: function(!editing.EditingContext,
                                   !editing.ReadOnlySelection),
 *    previousNode: function(?Node) : ?Node
 *  }
 * }}
 */
var editing;

/**
 * @constructor
 * @final
 * @param {!editing.Editor} editor
 * @param {string} name
 * @param {!editing.ReadOnlySelection} selection
 */
editing.EditingContext = function(editor, name, selection) {};

/** @type {!editing.ReadOnlySelection} */
editing.EditingContext.prototype.endingSelection;

/** @type {!editing.Operation} */
editing.EditingContext.prototype.operations;

/** @param {!editing.ReadOnlySelection} selection */
editing.EditingContext.prototype.setEndingSelection = function(selection) {};

/**
 * @this {!editing.EditingContext}
 * @param {!Text} node
 * @param {number} offset
 * @return {!Text}
 */
editing.EditingContext.prototype.splitText = function(node, offset) {};

/** @type {!editing.ReadOnlySelection} */
editing.EditingContext.prototype.startingSelection;

/**
 * @constructor
 * @final
 * @param {!Document} document
 */
editing.Editor;

/** @type {!Document} */
editing.Editor.prototype.document;

/**
 * @constructor
 * @param {string} name
 */
editing.Operation = function(name) {};

/** @type {!function()} */
editing.Operation.prototype.execute = function() {};

/** @type {string} */
editing.Operation.prototype.operationName;

/** @type {!function()} */
editing.Operation.prototype.redo = function() {};

/** @type {!function()} */
editing.Operation.prototype.undo = function() {};

/**
 * @constructor
 * @extends {editing.Operation}
 * @final
 * @param {!Node} parentNode
 * @param {!Node} newChild
 */
editing.AppendChild = function(parentNode, newChild) {}

/**
 * @constructor
 * @extends {editing.Operation}
 * @final
 * @param {!Node} parentNode
 * @param {!Node} newChild
 * @param {?Node} refChild
 */
editing.InsertBefore = function(parentNode, newChild, refChild) {};

/**
 * @constructor
 * @extends {editing.Operation}
 * @final
 * @param {!Element} element
 * @param {string} attrName
 */
editing.RemoveAttribute = function(element, attrName) {};

/**
 * @constructor
 * @extends {editing.Operation}
 * @final
 * @param {!Node} parentNode
 * @param {!Node} oldChild
 */
editing.RemoveChild = function(parentNode, oldChild) {};

/**
 * @constructor
 * @extends {editing.Operation}
 * @final
 * @param {!Node} parentNode
 * @param {!Node} newChild
 * @param {!Node} oldChild
 */
editing.ReplaceChild = function(parentNode, newChild, oldChild) {};

/**
 * @constructor
 * @extends {editing.Operation}
 * @final
 * @param {!Element} element
 * @param {string} attrName
 * @param {string} newValue
 */
editing.SetAttribute = function(element, attrName, newValue) {};

/**
 * @constructor
 * @extends {editing.Operation}
 * @final
 * @param {!Element} element
 * @param {string} propertyName
 * @param {string} newValue
 */
editing.SetStyle = function(element, propertyName, newValue) {};

/**
 * @constructor
 * @extends {editing.Operation}
 * @final
 * @param {!Text} textNode
 * @param {!Text} newNode
 */
editing.SplitText = function(textNode, newNode) {};

/**
 * @constructor
 * @final
 * @param {?Node} anchorNode
 * @param {number} anchorOffset
 * @param {?Node} focusNode
 * @param {number} focusOffset
 */
editing.ReadOnlySelection = function(anchorNode, anchorOffset, focusNode,
                                     focusOffset, direction) {};

/** @type {!Node} */
editing.ReadOnlySelection.prototype.anchorNode;

/** @type {number} */
editing.ReadOnlySelection.prototype.anchorOffset;

/** @type {!editing.SelectionDirection} */
editing.ReadOnlySelection.prototype.direction;

/** @type {!Node} */
editing.ReadOnlySelection.prototype.endContainer;

/** @type {number} */
editing.ReadOnlySelection.prototype.endOffset;

/** @type {!Node} */
editing.ReadOnlySelection.prototype.focusNode;

/** @type {number} */
editing.ReadOnlySelection.prototype.focusOffset;

/** @type {boolean} */
editing.ReadOnlySelection.prototype.isCaret;

/** @type {boolean} */
editing.ReadOnlySelection.prototype.isEmpty;

/** @type {boolean} */
editing.ReadOnlySelection.prototype.isRange;

/** @type {!Node} */
editing.ReadOnlySelection.prototype.startContainer;

/** @type {number} */
editing.ReadOnlySelection.prototype.startOffset;

/** @enum {string} */
editing.SelectionDirection = {
  ANCHOR_IS_START: 'ANCHOR_IS_START',
  FOCUS_IS_START: 'FOCUS_IS_START'
};

/**
 * @typedef {function(!editing.EditingContext, boolean=, string=) : boolean}
 */
var CommandFunction;

/**
 * @typedef {{
 *  categories: string,
 *  contextModel: (!Array.<string>|!Set.<string>),
 *  usableContexts: (!Array.<string>|!Set.<string>)
 * }}
 */
var ContentModel;

/** @enum {string} */
editing.CONTENT_CATEGORY = {
  EMBEDDED: 'EMBEDDED',
  FLOW: 'FLOW',
  HEADING: 'HEADING',
  INTERACTIVE: 'INTERACTIVE',
  PALPABLE: 'PALPABLE',
  PHRASING: 'PHRASING',
  SECTIONING_ROOT: 'SECTIONING_ROOT',
  TRANSPARENT: 'TRANSPARENT',
};

/**
 * @type {{
 *  browserId: string,
 *  define: function(string, !function())
 * }}
 */
var testing;
